package life.mahu.community.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import life.mahu.community.exception.CustomizeErrorCode;
import life.mahu.community.exception.CustomizeException;
import life.mahu.community.mapper.*;
import life.mahu.community.dto.CommentDTO;
import life.mahu.community.enums.CommentTypeEnum;
import life.mahu.community.enums.NotificationStatusEnum;
import life.mahu.community.enums.NotificationTypeEnum;
import life.mahu.community.model.*;
import life.mahu.community.mapper.*;
import life.mahu.community.model.*;
import life.mahu.community.util.RedisUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class CommentService {

    @Autowired
    private CommentMapper commentMapper;

    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private QuestionExtMapper questionExtMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private CommentExtMapper commentExtMapper;

    @Autowired
    private NotificationMapper notificationMapper;

    @Autowired
    private UserCommentMapper userCMapper;

    @Resource
    private RedisUtil redis;

    // redis中存储的过期时间s
    private static int ExpireTime = 60*60;

    @Transactional
    public void insert(Comment comment, User commentator) {
        if (comment.getParentId() == null || comment.getParentId() == 0) {
            throw new CustomizeException(CustomizeErrorCode.TARGET_PARAM_NOT_FOUND);
        }
        if (comment.getType() == null || !CommentTypeEnum.isExist(comment.getType())) {
            throw new CustomizeException(CustomizeErrorCode.TYPE_PARAM_WRONG);
        }
        if (comment.getType() == CommentTypeEnum.COMMENT.getType()) {
            // 回复评论
            Comment dbComment = commentMapper.selectByPrimaryKey(comment.getParentId());
            if (dbComment == null) {
                throw new CustomizeException(CustomizeErrorCode.COMMENT_NOT_FOUND);
            }

            // 回复问题
            Question question = questionMapper.selectByPrimaryKey(dbComment.getParentId());
            if (question == null) {
                throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
            }

            commentMapper.insert(comment);

            // 增加评论数
            Comment parentComment = new Comment();
            parentComment.setId(comment.getParentId());
            parentComment.setCommentCount(1);
            commentExtMapper.incCommentCount(parentComment);

            // 创建通知
            createNotify(comment, dbComment.getCommentator(), commentator.getName(), question.getTitle(), NotificationTypeEnum.REPLY_COMMENT, question.getId());
        } else {
            // 回复问题
            Question question = questionMapper.selectByPrimaryKey(comment.getParentId());
            if (question == null) {
                throw new CustomizeException(CustomizeErrorCode.QUESTION_NOT_FOUND);
            }
            comment.setCommentCount(0);
            commentMapper.insert(comment);
            question.setCommentCount(1);
            questionExtMapper.incCommentCount(question);

            // 创建通知
            createNotify(comment, question.getCreator(), commentator.getName(), question.getTitle(), NotificationTypeEnum.REPLY_QUESTION, question.getId());
        }
    }

    private void createNotify(Comment comment, Long receiver, String notifierName, String outerTitle, NotificationTypeEnum notificationType, Long outerId) {
        if (receiver == comment.getCommentator()) {
            return;
        }
        Notification notification = new Notification();
        notification.setGmtCreate(System.currentTimeMillis());
        notification.setType(notificationType.getType());
        notification.setOuterid(outerId);
        notification.setNotifier(comment.getCommentator());
        notification.setStatus(NotificationStatusEnum.UNREAD.getStatus());
        notification.setReceiver(receiver);
        notification.setNotifierName(notifierName);
        notification.setOuterTitle(outerTitle);
        notificationMapper.insert(notification);
    }

    public List<CommentDTO> listByTargetId(Long id, CommentTypeEnum type) {
        CommentExample commentExample = new CommentExample();
        commentExample.createCriteria()
                .andParentIdEqualTo(id)
                .andTypeEqualTo(type.getType());
        commentExample.setOrderByClause("gmt_create desc");
        List<Comment> comments = commentMapper.selectByExample(commentExample);

        if (comments.size() == 0) {
            return new ArrayList<>();
        }
        // 获取去重的评论人
        Set<Long> commentators = comments.stream().map(comment -> comment.getCommentator()).collect(Collectors.toSet());
        List<Long> userIds = new ArrayList();
        userIds.addAll(commentators);


        // 获取评论人并转换为 Map
        UserExample userExample = new UserExample();
        userExample.createCriteria()
                .andIdIn(userIds);
        List<User> users = userMapper.selectByExample(userExample);
        Map<Long, User> userMap = users.stream().collect(Collectors.toMap(user -> user.getId(), user -> user));


        // 转换 comment 为 commentDTO
        List<CommentDTO> commentDTOS = comments.stream().map(comment -> {
            CommentDTO commentDTO = new CommentDTO();
            BeanUtils.copyProperties(comment, commentDTO);
            commentDTO.setUser(userMap.get(comment.getCommentator()));
            return commentDTO;
        }).collect(Collectors.toList());

        return commentDTOS;
    }

    public boolean insertOrUpdateUC(UserComment userC, Integer type){
        UserCommentExample UCExample = new UserCommentExample();
        UserCommentExample.Criteria criteria = UCExample.createCriteria();

        criteria.andUserIdEqualTo(userC.getUserId());//根据用户Id和评论id查找用户的点赞记录
        if(userC.getCommentId() != 0){
            criteria.andCommentIdEqualTo(userC.getCommentId());
        }

        //更新数据库及缓存
        List<UserComment> userQuestions = userCMapper.selectByExample(UCExample);
        if (type == 1) {//点赞
            if (userQuestions.size() != 0) {//如果明明点赞过了却可以再次点赞则系统报错
                return false;
            }
            userCMapper.insert(userC);
            redis.listLSet("muhuUserId="+ userC.getUserId(), userC.getCommentId(), ExpireTime);
        }else{//取消点赞
            if (userQuestions.size() == 0) {//如果明明没有点赞过却不可以取消点赞则系统报错
                return false;
            }
            userCMapper.deleteByExample(UCExample);
            redis.lRemove("muhuUserId="+ userC.getUserId(), 1, userC.getCommentId());
        }

        //更新Comment的like_count字段
        Comment comment = new Comment();
        comment.setId(userC.getCommentId());
        comment.setLikeCount((long)type);
        commentExtMapper.incLikeCount(comment);

        //点赞通知
        if (type == 1) {

        }
        return true;

    }

    public List<Long> listByUserID(Long id) {
        UserCommentExample UCExample = new UserCommentExample();
        UCExample.createCriteria().andUserIdEqualTo(id);

        List<Long> list = new ArrayList<>();
        List<UserComment> userCommentlist = userCMapper.selectByExample(UCExample);
        for (UserComment userComment : userCommentlist) {
            list.add(userComment.getCommentId());
        }
        return list;
    }

    public Boolean delCommentById(Long id) {
        int delUser = commentMapper.deleteByPrimaryKey(id);
        return delUser>0?true:false;
    }

    public PageInfo getCommentListPage(Comment comment, Integer page, Integer limit) {
        CommentExample commentExample = new CommentExample();
        CommentExample.Criteria criteria = commentExample.createCriteria();
        if (!(comment.getUname() == null  || "".equals(comment.getUname()))) {
            UserExample userExample = new UserExample();
            UserExample.Criteria userCriteria = userExample.createCriteria();
            userCriteria.andNameLike("%" + comment.getUname() + "%");
            List<User> users = userMapper.selectByExample(userExample);
            List<Long> userIds = new ArrayList<>();
            for (User user : users) {
                userIds.add(user.getId());
            }
            criteria.andCommentatorIn(userIds);
        }
        if (!(comment.getContent() == null || "".equals(comment.getContent()))) {
            criteria.andContentLike("%" + comment.getContent() + "%");
        }

        PageHelper.startPage(page, limit);
        List<Comment> commentList = commentMapper.selectByExampleGetAll(commentExample);
        return new PageInfo<Comment>(commentList);
    }

    public Comment getCommentById(Long id) {
        return commentMapper.selectByPrimaryKeyGetALL(id);
    }

    public Boolean insertComment(Comment comment) {
        comment.setGmtCreate(System.currentTimeMillis());
        comment.setGmtModified(System.currentTimeMillis());
        comment.setCommentator(1L);
        int insert = commentMapper.insert(comment);
        return insert>0?true:false;
    }

    public Boolean updateCommentById(Comment comment) {
        Comment loseComment = commentMapper.selectByPrimaryKey(comment.getId());
        comment.setGmtModified(System.currentTimeMillis());
        comment.setGmtCreate(loseComment.getGmtCreate());
        int update = commentMapper.updateByPrimaryKey(comment);
        return update>0?true:false;
    }

    //根据parentId(根据问题id来删除评论)
    public Boolean delCommentByParentId(Long parentId) {
        CommentExample commentExample = new CommentExample();
        CommentExample.Criteria criteria = commentExample.createCriteria();
        criteria.andParentIdEqualTo(parentId);
        int delUser = commentMapper.deleteByExample(commentExample);
        return delUser>0?true:false;
    }

    //获取问题的所有评论Id
    public List<Long> queryByParentId(Long parentId){
        CommentExample commentExample = new CommentExample();
        CommentExample.Criteria criteria = commentExample.createCriteria();
        criteria.andParentIdEqualTo(parentId);
        List<Long> cid=new ArrayList<>();
        List<Comment> coms=commentMapper.selectByExample(commentExample);
        for(int i=0,length=coms.size();i<length;i++){
            cid.add(coms.get(i).getId());
        }
        return cid;
    }

}
